#include "stdafx.h"
#ifdef LIT_OGRE_SUPPORT
#include "LitPhysicsManager.h"

namespace Lit
{
	LIT_API const String PhysicsManager::DEFAULT_WORLD_NAME = "__DEFAULT__WORLD__";

	PhysicsManager::PhysicsManager(void)
		: CoreComponent()
		, mPause( false )
	{
	}

	PhysicsManager::~PhysicsManager(void)
	{
	}
		
	bool PhysicsManager::isPaused() const{ return mPause; }
	void PhysicsManager::setPaused( bool state ){ mPause = state; }

	void PhysicsManager::initialise( const OgreDetails &details ){
	}
	bool PhysicsManager::renderOneFrame( float dt ){
		if( mPause ) return true;
		for( auto i=mWorlds.begin(); i!=mWorlds.end(); i++ )
		{
			if( i->second )
			{
				i->second->update( dt );
			}
		}
		return true;
	}
	void PhysicsManager::shutdown()
	{
		destroyWorlds( );
	}

	Physics::WorldPtr PhysicsManager::createWorld( const String &name, Physics::PlatformOptimisation optimis, Physics::SolverModel solver, const Lit::AABB& dimensions )
	{
		if( hasWorld(name) )
			throw Lit::ItemDuplicate( "World "+name, "PhysicsManager", EXC_LOC );
		Physics::WorldPtr w(new Physics::World( name, optimis, solver, dimensions ));
		mWorlds[name] = w;
		return w;
	}
	bool PhysicsManager::hasWorld( const String &name ) const{ return mWorlds.find(name) != mWorlds.end(); }
	Physics::WorldPtr& PhysicsManager::getWorld( const String &name ){ 
		if( !hasWorld(name) ) throw Lit::ItemMissing( "World "+name, "PhysicsManager", EXC_LOC );
		return mWorlds.find(name)->second;
	}
	const Physics::WorldPtr& PhysicsManager::getWorld( const String &name ) const{ 
		if( !hasWorld(name) ) throw Lit::ItemMissing( "World "+name, "PhysicsManager", EXC_LOC );
		return mWorlds.find(name)->second;
	}
	void PhysicsManager::clearWorlds( )
	{
		for( auto i=mWorlds.begin(); i!=mWorlds.end(); i++ )
		{
			if(i->second) i->second->clear();
		}
	}
	void PhysicsManager::destroyWorlds( )
	{
		for( auto i=mWorlds.begin(); i!=mWorlds.end(); i++ )
		{
			if(i->second) i->second.destroy();
		}
		mWorlds.clear();
	}
	void PhysicsManager::clearWorld( Physics::WorldPtr world )
	{
		if( !hasWorld(world->getName()) ) throw Lit::ItemMissing("World "+world->getName(), "PhysicsManager", EXC_LOC);
		auto i=mWorlds.find(world->getName());
		if( i->second ) i->second->clear();
	}
	void PhysicsManager::destroyWorld( Physics::WorldPtr ptr )
	{
		auto i = mWorlds.find(ptr->getName());
		if( i==mWorlds.end() )
			throw Lit::ItemMissing( "World "+ptr->getName(), "PhysicsManager", EXC_LOC );
		if( i->second ) i->second.destroy();
		mWorlds.erase( i );
	}
	void PhysicsManager::clearWorld( const String &name )
	{
		if( !hasWorld(name) ) throw Lit::ItemMissing("World "+name, "PhysicsManager", EXC_LOC);
		auto i=mWorlds.find(name);
		if( i->second ) i->second->clear();
	}
	void PhysicsManager::destroyWorld( const String &name )
	{
		if( !hasWorld(name) )
			throw Lit::ItemMissing( "World "+name, "PhysicsManager", EXC_LOC );
		auto i = mWorlds.find(name);
		if( i->second ) i->second.destroy();
		mWorlds.erase( i );
	}
};

#endif